{-# LANGUAGE TypeOperators              #-}
{-# OPTIONS -Wall #-}

--------------------------------------------------------------------------------
-- |
-- Module      :  Ochre.Language.SignalGenerators
-- Copyright   :  (c) Stephen Tetley 2012-2013
-- License     :  BSD3
--
-- Maintainer  :  stephen.tetley@gmail.com
-- Stability   :  unstable
-- Portability :  GHC
--
-- Signal generating opcodes.
-- 
--------------------------------------------------------------------------------

module Ochre.Language.SignalGenerators
  (

  -- * Linear and exponential generators
    line
  , expon
  , linseg
  , linsegr
  , expseg
  , expsegr
  , expsega
  , transeg

  , adsr
  , adsr_

  , madsr
  , madsr_
  , xadsr
  , xadsr_
  , mxadsr
  , mxadsr_

  -- * Table access
  , table
  , table_

  , tablei
  , tablei_
  
  , table3
  , table3_

  , oscil1
  , oscil1i
  , osciln

  -- * Phasors
  , phasor
  , phasor_
  , phasorbnk
  , phasorbnk_


  -- * Basic oscillators
  , oscil
  , oscil_
  , oscili
  , oscili_
  , oscil3
  , oscil3_
  , poscil
  , poscil_
  , poscil3
  , poscil3_
  , lfo
  , lfo_

  -- * Dynamic spectrum oscillators
  , buzz
  , buzz_
  , gbuzz
  , gbuzz_
  , vco

  -- * Additive synthesis / resynthesis
  , adsyn
  , adsynt
  , adsynt_
  , hsboscil
  , hsboscil_

  -- * FM synthesis
  , foscil
  , foscil_
  , foscili
  , foscili_
  , fmvoice
  , fmbell
  , fmrhode
  , fmwurlie
  , fmmetal
  , fmb3
  , fmpercfl

  -- * Sample playback - full spec versions todo
  , loscil
  , loscilS
  , loscil3
  , loscil3S
  , lposcil
  , lposcil3

  -- * Granular synthesis
  , fof
  , fof2
  , fog
  , grain
  , grain2
  , grain3
  , granule
  , partikkel

  -- * Models and emulations
  , moog
  , shaker
  , marimba
  , vibes
  , mandol
  , gogobel
  , voice
  , lorenz
  , planet

  -- * Random noise generators
  , rand
  , randh
  , randi
  , linrand
  , trirand
  , exprand
  , bexprand
  , cauchy
  , pcauchy
  , poisson
  , gauss
  , weibull
  , betarand
  , unirand

  -- * Waveguide physical modeling
  , pluck
  , repluck
  , wgbow
  , wgbowedbar
  , wgbrass
  , wgclar
  , wgflute
  , wgpluck
  , wgpluck2
  , wguide1
  , wguide2

  ) where


import Ochre.Language.Prim

--------------------------------------------------------------------------------
-- Linear and Exponential generators





line :: KA_Signal a => IFloat -> IFloat -> IFloat -> GenSig a
line ia idur1 ib = 
    opcode1 "line" [ getPValue ia, getPValue idur1
                   , getPValue ib ]



expon :: KA_Signal a => IFloat -> IFloat -> IFloat -> GenSig a
expon ia idur1 ib = 
    opcode1 "expon" [ getPValue ia, getPValue idur1
                    , getPValue ib ]



linseg :: KA_Signal a 
       => IFloat -> [IFloat ::: IFloat] -> GenSig a
linseg ia xss =  
    opcode1 "linseg" $ getPValue ia : concatMap fn xss
  where
    fn (idur ::: ib) = [getPValue idur, getPValue ib]

    


linsegr :: KA_Signal a 
        => IFloat -> [IFloat ::: IFloat] -> IFloat ->  IFloat 
        -> GenSig a
linsegr ia xss irel iz =
    opcode1 "linsegr" $ getPValue ia : concatMap fn xss ++ release
  where
    fn (idur ::: ib) = [getPValue idur, getPValue ib]
    release          = [getPValue irel, getPValue iz]



expseg :: KA_Signal a 
       => IFloat -> [IFloat ::: IFloat] -> GenSig a
expseg ia xss = 
    opcode1 "expseg" $ getPValue ia : concatMap fn xss
  where
    fn (idur ::: ib) = [getPValue idur, getPValue ib]


expsegr :: KA_Signal a
        => IFloat -> [IFloat ::: IFloat] -> IFloat -> IFloat 
        -> GenSig a
expsegr ia xss irel iz = 
    opcode1 "expsegr" $ getPValue ia : concatMap fn xss ++ release
  where
    fn (idur ::: ib) = [getPValue idur, getPValue ib]
    release          = [ getPValue irel, getPValue iz ]


expsega :: IFloat -> [IFloat ::: IFloat] -> GenASig
expsega ia xss =
    opcode1 "expsega" $ getPValue ia : concatMap fn xss 
  where
    fn (idur ::: ib) = [getPValue idur, getPValue ib]
 

transeg :: KA_Signal a 
        => IFloat -> [IFloat ::: IFloat ::: IFloat] -> GenSig a
transeg ia xss = 
    opcode1 "transeg" $ getPValue ia : concatMap fn xss 
  where
    fn (idur ::: (itype ::: ib)) = [ getPValue idur, getPValue itype
                                   , getPValue ib ]


adsr :: KA_Signal a => IFloat -> IFloat -> IFloat -> IFloat -> GenSig a
adsr iatt idec islev irel = 
    opcode1 "adsr" [ getPValue iatt,  getPValue idec
                   , getPValue islev, getPValue irel ]
                   


adsr_ :: KA_Signal a 
      => IFloat -> IFloat -> IFloat -> IFloat -> IFloat 
      -> GenSig a
adsr_ iatt idec islev irel idel = 
    opcode1 "adsr" [ getPValue iatt,  getPValue idec
                   , getPValue islev, getPValue irel
                   , getPValue idel ]

madsr :: KA_Signal a
      => IFloat -> IFloat -> IFloat -> IFloat -> GenSig a
madsr iatt idec islev irel = 
    opcode1 "madsr" [ getPValue iatt,  getPValue idec
                    , getPValue islev, getPValue irel ]


madsr_ :: KA_Signal a
       => IFloat -> IFloat -> IFloat -> IFloat -> IFloat 
       -> GenSig a
madsr_ iatt idec islev irel idel = 
    opcode1 "madsr" [ getPValue iatt,  getPValue idec
                    , getPValue islev, getPValue irel
                    , getPValue idel ]


xadsr :: KA_Signal a
      => IFloat -> IFloat -> IFloat -> IFloat -> GenSig a
xadsr iatt idec islev irel = 
    opcode1 "xadsr" [ getPValue iatt,  getPValue idec
                    , getPValue islev, getPValue irel ]


xadsr_ :: KA_Signal a 
       => IFloat -> IFloat -> IFloat -> IFloat -> IFloat 
       -> GenSig a
xadsr_ iatt idec islev irel idel = 
    opcode1 "xadsr" [ getPValue iatt,  getPValue idec
                    , getPValue islev, getPValue irel
                    , getPValue idel ]


mxadsr :: KA_Signal a
       => IFloat -> IFloat -> IFloat -> IFloat -> GenSig a
mxadsr iatt idec islev irel = 
    opcode1 "mxadsr" [ getPValue iatt,  getPValue idec
                     , getPValue islev, getPValue irel ]


mxadsr_ :: KA_Signal a
         => IFloat -> IFloat -> IFloat -> IFloat -> IFloat 
         -> GenSig a
mxadsr_ iatt idec islev irel idel = 
    opcode1 "mxadsr" [ getPValue iatt,  getPValue idec
                     , getPValue islev, getPValue irel
                     , getPValue idel ]

--------------------------------------------------------------------------------
-- Table access


-- | Note - index not an Int... 
--
table :: IKA_Signal a => Sig a -> TableIx -> GenSig a
table xndx ifn = 
    opcode1 "table" [ getPValue xndx,  getPValue ifn ]

table_ :: IKA_Signal a 
       => Sig a -> TableIx -> IFloat -> IFloat -> IFloat 
       -> GenSig a
table_ xndx ifn ixmode ixoff iwrap = 
    opcode1 "table" [ getPValue xndx,   getPValue ifn
                    , getPValue ixmode, getPValue ixoff
                    , getPValue iwrap ]


tablei :: IKA_Signal a => Sig a -> TableIx -> GenSig a
tablei xndx ifn = 
    opcode1 "tablei" [ getPValue xndx,  getPValue ifn ]

tablei_ :: IKA_Signal a
        => Sig a -> TableIx -> IFloat -> IFloat -> IFloat 
        -> GenSig a
tablei_ xndx ifn ixmode ixoff iwrap = 
    opcode1 "tablei" [ getPValue xndx,   getPValue ifn
                     , getPValue ixmode, getPValue ixoff
                     , getPValue iwrap ]



table3 :: IKA_Signal a => Sig a -> TableIx -> GenSig a
table3 xndx ifn = 
    opcode1 "table" [ getPValue xndx,  getPValue ifn ]


table3_ :: IKA_Signal a
        => Sig a -> TableIx -> IFloat -> IFloat -> IFloat 
        -> GenSig a
table3_ xndx ifn ixmode ixoff iwrap = 
    opcode1 "table3" [ getPValue xndx,   getPValue ifn
                     , getPValue ixmode, getPValue ixoff
                     , getPValue iwrap ]




--------------------------------------------------------------------------------
--


oscil1 :: IFloat -> KSig -> IFloat -> IInt -> GenKSig
oscil1 idel kamp idur ifn = 
    opcode1 "oscil1" [ getPValue idel, getPValue kamp
                     , getPValue idur, getPValue ifn ]
         


oscil1i :: IFloat -> KSig -> IFloat -> IInt -> GenKSig
oscil1i idel kamp idur ifn = 
    opcode1 "oscil1i" [ getPValue idel, getPValue kamp
                      , getPValue idur, getPValue ifn ]


osciln :: KSig -> IFloat -> IInt -> IFloat -> GenKSig
osciln kamp ifrq ifn itimes = 
    opcode1 "osciln" [ getPValue kamp, getPValue ifrq
                     , getPValue ifn,  getPValue itimes ]


--------------------------------------------------------------------------------
-- Phasors

-- class CPhasor rate where


phasor :: KA_Signal a => Sig r1 -> GenSig a
phasor xcps = 
    opcode1 "phasor" [ getPValue xcps ]

phasor_ :: KA_Signal a => Sig r1 -> IFloat -> GenSig a
phasor_ xcps iphs = 
    opcode1 "phasor" [ getPValue xcps, getPValue iphs ]


phasorbnk :: KA_Signal a 
          => Sig r1 -> KSig -> IFloat -> GenSig a
phasorbnk xcps kindx icnt = 
    opcode1 "phasorbnk" [ getPValue xcps, getPValue kindx
                        , getPValue icnt ]


phasorbnk_  :: KA_Signal a 
            => Sig r1 -> KSig -> IFloat -> IFloat 
            -> GenSig a
phasorbnk_ xcps kindx icnt iphs = 
    opcode1 "phasorbnk" [ getPValue xcps, getPValue kindx
                        , getPValue icnt, getPValue iphs ]


--------------------------------------------------------------------------------
-- Basic oscillators


-- | upsample amp cps when necessary.
-- 
oscil :: KA_Signal a 
      => Sig a -> Sig a -> TableIx -> GenSig a
oscil xamp xcps ifn = 
    opcode1 "oscil" [ getPValue xamp, getPValue xcps
                    , getPValue ifn ]


oscil_ :: KA_Signal a
       => Sig a -> Sig a -> TableIx -> IFloat -> GenSig a
oscil_ xamp xcps ifn iphs = 
    opcode1 "oscil" [ getPValue xamp, getPValue xcps
                    , getPValue ifn,  getPValue iphs ]




-- | Prefer @oscil@ rather than this one...
--
oscili :: KA_Signal a
       => Sig a -> Sig a -> IInt -> GenSig a
oscili xamp xcps ifn = 
    opcode1 "oscili" [ getPValue xamp, getPValue xcps
                     , getPValue ifn ]


oscili_ :: KA_Signal a
        => Sig a -> Sig a -> IInt -> IFloat -> GenSig a
oscili_ xamp xcps ifn iphs = 
    opcode1 "oscili" [ getPValue xamp, getPValue xcps
                     , getPValue ifn,  getPValue iphs ]


oscil3 :: KA_Signal a => Sig a -> Sig a -> IInt -> GenSig a
oscil3 xamp xcps ifn = 
    opcode1 "oscil3"  [ getPValue xamp, getPValue xcps
                      , getPValue ifn ]


oscil3_ :: KA_Signal a 
        => Sig a -> Sig a -> IInt -> IFloat -> GenSig a
oscil3_ xamp xcps ifn iphs = 
    opcode1 "oscil3" [ getPValue xamp, getPValue xcps
                    , getPValue ifn,  getPValue iphs ]



poscil :: KA_Signal a 
       => Sig a -> Sig a -> IInt -> GenSig a
poscil xamp xcps ift = 
    opcode1 "poscil" [ getPValue xamp, getPValue xcps
                     , getPValue ift ]

poscil_ :: KA_Signal a 
        => Sig a -> Sig a -> IInt -> IFloat -> GenSig a
poscil_ xamp xcps ift iphs = 
    opcode1 "poscil" [ getPValue xamp, getPValue xcps
                     , getPValue ift,  getPValue iphs ]


poscil3 :: KA_Signal a => Sig a -> Sig a -> IInt -> GenSig a
poscil3 xamp xcps ift = 
    opcode1 "poscil3" [ getPValue xamp, getPValue xcps
                      , getPValue ift ]



poscil3_ :: KA_Signal a 
         => Sig a -> Sig a -> IInt -> IFloat -> GenSig a
poscil3_ xamp xcps ift iphs = 
    opcode1 "poscil3" [ getPValue xamp, getPValue xcps
                      , getPValue ift,  getPValue iphs ]



lfo :: KA_Signal a => Sig a -> Sig a -> GenSig a
lfo xamp xcps = 
    opcode1 "lfo" [ getPValue xamp, getPValue xcps ]


lfo_ :: KA_Signal a => Sig a -> Sig a -> IFloat -> GenSig a
lfo_ xamp xcps itype = 
    opcode1 "lfo" [ getPValue xamp, getPValue xcps
                  , getPValue itype ]

--------------------------------------------------------------------------------
-- Dynamic spectrum oscillators

-- TODO - what does the x prefix convention mean for Csound?



-- | upsample @xamp@ and @xps@ where necessary.
--
buzz :: ASig -> ASig -> KSig -> IInt -> GenASig
buzz xamp xcps knh ifn = 
    opcode1 "buzz" [ getPValue xamp, getPValue xcps
                   , getPValue knh,  getPValue ifn ]


-- | upsample @xamp@ and @xps@ where necessary.
--
buzz_ :: ASig -> ASig -> KSig 
      -> IInt -> IFloat -> GenASig
buzz_ xamp xcps knh ifn iphs = 
    opcode1 "buzz" [ getPValue xamp, getPValue xcps
                   , getPValue knh,  getPValue ifn
                   , getPValue iphs ]



gbuzz :: ASig -> ASig -> KSig -> KSig 
      -> KSig -> IInt -> GenASig
gbuzz xamp xcps knh klh kr ifn = 
    opcode1 "gbuzz" [ getPValue xamp, getPValue xcps
                    , getPValue knh,  getPValue klh
                    , getPValue kr,   getPValue ifn ]
 


gbuzz_ :: ASig -> ASig -> KSig 
       -> KSig -> KSig -> IInt -> IFloat 
       -> GenASig
gbuzz_ xamp xcps knh klh kr ifn iphs = 
    opcode1 "gbuzz" [ getPValue xamp, getPValue xcps
                    , getPValue knh,  getPValue klh
                    , getPValue kr,   getPValue ifn
                    , getPValue iphs ]

vco :: KSig -> KSig -> IFloat -> KSig 
    -> TableIx -> IFloat -> GenASig
vco kamp kfqc iwave kpw ifn imaxd = 
    opcode1 "vco" [ getPValue kamp,  getPValue kfqc
                  , getPValue iwave, getPValue kpw
                  , getPValue ifn,   getPValue imaxd ]


--------------------------------------------------------------------------------
-- Additive synthesis / resynthesis


adsyn :: KSig -> KSig -> KSig -> IString -> GenASig
adsyn kamod kfmod ksmod ifilcod = 
    opcode1 "adsyn" [ getPValue kamod, getPValue kfmod
                    , getPValue ksmod, getPValue ifilcod ]
    

adsynt :: KSig -> KSig 
       -> TableIx -> TableIx -> TableIx -> IFloat -> GenASig
adsynt kamp kcps iwfn ifreqfn iampfn icnt = 
    opcode1 "adsynt" [ getPValue kamp,   getPValue kcps
                     , getPValue iwfn,   getPValue ifreqfn
                     , getPValue iampfn, getPValue icnt ]


adsynt_ :: KSig -> KSig 
        -> TableIx -> TableIx -> TableIx -> IFloat -> IFloat 
        -> GenASig
adsynt_ kamp kcps iwfn ifreqfn iampfn icnt iphs = 
    opcode1 "adsynt" [ getPValue kamp,   getPValue kcps
                     , getPValue iwfn,   getPValue ifreqfn
                     , getPValue iampfn, getPValue icnt
                     , getPValue iphs ]

hsboscil :: KSig -> KSig -> KSig 
         -> IFloat -> TableIx -> TableIx -> GenASig
hsboscil kamp ktone kbrite ibasfreq iwnfn ioctfn = 
    opcode1 "hsboscil" [ getPValue kamp,    getPValue ktone
                       , getPValue kbrite,  getPValue ibasfreq
                       , getPValue iwnfn,   getPValue ioctfn ]

hsboscil_ :: KSig -> KSig -> KSig 
          -> IFloat -> TableIx -> TableIx -> IFloat -> IFloat
          -> GenASig
hsboscil_ kamp ktone kbrite ibasfreq iwnfn ioctfn ioctcnt iphs = 
    opcode1 "hsboscil" [ getPValue kamp,    getPValue ktone
                       , getPValue kbrite,  getPValue ibasfreq
                       , getPValue iwnfn,   getPValue ioctfn
                       , getPValue ioctcnt, getPValue iphs ]


--------------------------------------------------------------------------------
-- FM Synthesis



foscil :: ASig -> KSig -> KSig -> KSig -> KSig -> TableIx
       -> GenASig
foscil xamp kcps kcar kmod kndx ifn = 
    opcode1 "foscil" [ getPValue xamp, getPValue kcps
                     , getPValue kcar, getPValue kmod
                     , getPValue kndx, getPValue ifn ]


foscil_ :: ASig -> KSig -> KSig 
        -> KSig -> KSig -> TableIx -> IFloat 
        -> GenASig
foscil_ xamp kcps kcar kmod kndx ifn iphs = 
    opcode1 "foscil" [ getPValue xamp, getPValue kcps
                     , getPValue kcar, getPValue kmod
                     , getPValue kndx, getPValue ifn
                     , getPValue iphs ]



foscili :: ASig -> KSig -> KSig 
        -> KSig -> KSig -> TableIx
        -> GenASig
foscili xamp kcps kcar kmod kndx ifn = 
    opcode1 "foscili" [ getPValue xamp, getPValue kcps
                      , getPValue kcar, getPValue kmod
                      , getPValue kndx, getPValue ifn ]


-- | Upsample @xamp@ if necessary.
--
foscili_ :: ASig -> KSig -> KSig 
         -> KSig -> KSig -> TableIx -> IFloat 
         -> GenASig
foscili_ xamp kcps kcar kmod kndx ifn iphs = 
    opcode1 "foscili" [ getPValue xamp, getPValue kcps
                      , getPValue kcar, getPValue kmod
                      , getPValue kndx, getPValue ifn
                      , getPValue iphs ]


fmvoice :: KSig -> KSig -> KSig 
        -> KSig -> KSig -> KSig
        -> TableIx -> TableIx -> TableIx -> TableIx -> TableIx
        -> GenASig
fmvoice kamp kfreq kvowel ktilt kvibamt kvibrate ifn1 ifn2 ifn3 ifn4 ifnv = 
    opcode1 "fmvoice" [ getPValue kamp,    getPValue kfreq
                      , getPValue kvowel,  getPValue ktilt
                      , getPValue kvibamt, getPValue kvibrate
                      , getPValue ifn1,    getPValue ifn2
                      , getPValue ifn3,    getPValue ifn4
                      , getPValue ifnv ]

fmbell :: KSig -> KSig -> KSig 
       -> KSig -> KSig -> KSig
       -> TableIx -> TableIx -> TableIx -> TableIx -> TableIx
       -> GenASig
fmbell kamp kfreq kc1 kc2 kvdepth kvrate ifn1 ifn2 ifn3 ifn4 ifnv = 
    opcode1 "fmbell" [ getPValue kamp,    getPValue kfreq
                     , getPValue kc1,     getPValue kc2
                     , getPValue kvdepth, getPValue kvrate
                     , getPValue ifn1,    getPValue ifn2
                     , getPValue ifn3,    getPValue ifn4
                     , getPValue ifnv ]


fmrhode :: KSig -> KSig -> KSig 
        -> KSig -> KSig -> KSig
        -> TableIx -> TableIx -> TableIx -> TableIx -> TableIx
        -> GenASig
fmrhode kamp kfreq kc1 kc2 kvdepth kvrate ifn1 ifn2 ifn3 ifn4 ifnv = 
    opcode1 "fmrhode" [ getPValue kamp,    getPValue kfreq
                      , getPValue kc1,     getPValue kc2
                      , getPValue kvdepth, getPValue kvrate
                      , getPValue ifn1,    getPValue ifn2
                      , getPValue ifn3,    getPValue ifn4
                      , getPValue ifnv ]

fmwurlie :: KSig -> KSig -> KSig 
         -> KSig -> KSig -> KSig
         -> TableIx -> TableIx -> TableIx -> TableIx -> TableIx
         -> GenASig
fmwurlie kamp kfreq kc1 kc2 kvdepth kvrate ifn1 ifn2 ifn3 ifn4 ifnv = 
    opcode1 "fmwurlie" [ getPValue kamp,    getPValue kfreq
                       , getPValue kc1,     getPValue kc2
                       , getPValue kvdepth, getPValue kvrate
                       , getPValue ifn1,    getPValue ifn2
                       , getPValue ifn3,    getPValue ifn4
                       , getPValue ifnv ]


fmmetal :: KSig -> KSig -> KSig 
        -> KSig -> KSig -> KSig
        -> TableIx -> TableIx -> TableIx -> TableIx -> TableIx
        -> GenASig
fmmetal kamp kfreq kc1 kc2 kvdepth kvrate ifn1 ifn2 ifn3 ifn4 ifnv = 
    opcode1 "fmmetal" [ getPValue kamp,    getPValue kfreq
                      , getPValue kc1,     getPValue kc2
                      , getPValue kvdepth, getPValue kvrate
                      , getPValue ifn1,    getPValue ifn2
                      , getPValue ifn3,    getPValue ifn4
                      , getPValue ifnv ]


fmb3 :: KSig -> KSig -> KSig 
     -> KSig -> KSig -> KSig
     -> TableIx -> TableIx -> TableIx -> TableIx -> TableIx
     -> GenASig
fmb3 kamp kfreq kc1 kc2 kvdepth kvrate ifn1 ifn2 ifn3 ifn4 ifnv = 
    opcode1 "fmb3" [ getPValue kamp,    getPValue kfreq
                   , getPValue kc1,     getPValue kc2
                   , getPValue kvdepth, getPValue kvrate
                   , getPValue ifn1,    getPValue ifn2
                   , getPValue ifn3,    getPValue ifn4
                   , getPValue ifnv ]

fmpercfl :: KSig -> KSig -> KSig 
         -> KSig -> KSig -> KSig        
         -> TableIx -> TableIx -> TableIx -> TableIx -> TableIx
         -> GenASig
fmpercfl kamp kfreq kc1 kc2 kvdepth kvrate ifn1 ifn2 ifn3 ifn4 ifnv = 
    opcode1 "fmpercfl" [ getPValue kamp,    getPValue kfreq
                       , getPValue kc1,     getPValue kc2
                       , getPValue kvdepth, getPValue kvrate
                       , getPValue ifn1,    getPValue ifn2
                       , getPValue ifn3,    getPValue ifn4
                       , getPValue ifnv ]


--------------------------------------------------------------------------------
-- Sample playback

-- Note - it seems idiomatic to want a stereo version with only
-- the mandatory args...


-- | Note - use 1 for ibase and kcps if the frequency is not known.
--
loscil :: ASig -> KSig -> TableIx 
       -> GenASig
loscil xamp kcps ifn = 
    opcode1 "loscil" [ getPValue xamp,    getPValue kcps
                     , getPValue ifn ]



-- | Stereo version of 'loscil'.
--
-- Note - use 1 for ibase and kcps if the frequency is not known.
--
loscilS :: ASig -> KSig -> TableIx
        -> GenSig2 ARate
loscilS xamp kcps ifn = 
    opcode1 "loscil" [ getPValue xamp,    getPValue kcps
                     , getPValue ifn ]




-- | Note - use 1 for ibase and kcps if the frequency is not known.
-- upsample @xamp@ if necessary.
--
loscil3 :: ASig -> KSig -> TableIx 
        -> GenASig
loscil3 xamp kcps ifn = 
    opcode1 "loscil3" [ getPValue xamp, getPValue kcps
                      , getPValue ifn ]



-- | Stereo version of 'loscil3'.
--
-- Note - use 1 for ibase and kcps if the frequency is not known.
-- upsample @xamp@ if necessary.
--
loscil3S :: ASig -> KSig -> TableIx
         -> GenSig2 ARate
loscil3S xamp kcps ifn = 
    opcode1 "loscil3" [ getPValue xamp, getPValue kcps
                      , getPValue ifn ]



lposcil :: KSig -> KSig 
        -> KSig -> KSig -> TableIx
        -> GenASig
lposcil kamp kfreqratio kloop kend ift = 
    opcode1 "lposcil" [ getPValue kamp,  getPValue kfreqratio
                      , getPValue kloop, getPValue kend
                      , getPValue ift ]



lposcil3 :: KSig -> KSig 
         -> KSig -> KSig -> TableIx
         -> GenASig
lposcil3 kamp kfreqratio kloop kend ift = 
    opcode1 "lposcil3" [ getPValue kamp,  getPValue kfreqratio
                       , getPValue kloop, getPValue kend
                       , getPValue ift ]


--------------------------------------------------------------------------------
-- Granular synthesis

fof :: IKA_Signal a
    => Sig a  -> Sig a  -> Sig a
    -> KSig -> KSig -> KSig
    -> KSig -> KSig -> IInt
    -> TableIx -> TableIx -> IFloat
    -> GenASig
fof xamp xfund xform koct kband kris kdur kdec iolaps ifna ifnb itotdur = 
    opcode1 "fof" [ getPValue xamp,   getPValue xfund
                  , getPValue xform,  getPValue koct
                  , getPValue kband,  getPValue kris
                  , getPValue kdur,   getPValue kdec
                  , getPValue iolaps, getPValue ifna
                  , getPValue ifnb,   getPValue itotdur ]




fof2 :: IKA_Signal a
     => Sig a  -> Sig a  -> Sig a
     -> KSig -> KSig -> KSig
     -> KSig -> KSig -> IInt
     -> TableIx -> TableIx -> IFloat
     -> KSig -> KSig
     -> GenASig
fof2 xamp xfund xform koct kband kris kdur kdec iolaps ifna ifnb itotdur 
     kphs kgliss = 
    opcode1 "fof2" [ getPValue xamp,   getPValue xfund
                   , getPValue xform,  getPValue koct
                   , getPValue kband,  getPValue kris
                   , getPValue kdur,   getPValue kdec
                   , getPValue iolaps, getPValue ifna
                   , getPValue ifnb,   getPValue itotdur 
                   , getPValue kphs,   getPValue kgliss ]



-- | 
--
-- > fog : xamp * xdens * xtrans * aspd * 
-- >       koct * kband * kris * kdur * kdec *
-- >       iolaps * ifna * ifnb * itotdur
-- >      -> ares
--
-- Note - kband etc. are not perhaps signals. 
-- Or maybe they are see @grain@...
--
fog             :: IKA_Signal a
                => Sig a -> Sig a -> Sig a
                -> Sig a -> KSig -> KSig
                -> KSig -> KSig -> KSig
                -> IFloat -> TableIx -> TableIx 
                -> IFloat
                -> GenASig
fog xamp xdens xtrans xspd koct kband kris kdur kdec iolaps ifna ifnb itotdur = 
    opcode1 "fog" [ getPValue xamp,   getPValue xdens
                  , getPValue xtrans, getPValue xspd
                  , getPValue koct,   getPValue kband
                  , getPValue kris,   getPValue kdur
                  , getPValue kdec,   getPValue iolaps
                  , getPValue ifna,   getPValue ifnb
                  , getPValue itotdur ]
    
-- | 
-- 
-- > grain : xamp * xpitch * xdens * kampoff * 
-- >         kpitchoff * kgdur * igfn * iwfn * imgdur
-- >        -> ares

grain           :: IKA_Signal a
                => Sig a -> Sig a -> Sig a
                -> KSig -> KSig -> KSig
                -> TableIx -> TableIx -> IFloat
                -> GenASig
grain xamp xpitch xdens kampoff kpitchoff kgdur igfn iwfn imgdur = 
    opcode1 "grain" [ getPValue xamp,      getPValue xpitch
                    , getPValue xdens,     getPValue kampoff
                    , getPValue kpitchoff, getPValue kgdur
                    , getPValue igfn,      getPValue iwfn
                    , getPValue imgdur ]


grain2 :: KSig -> KSig -> KSig -> IInt -> TableIx -> TableIx -> GenASig
grain2 kcps kfmd kgdur iovrlp kfn iwfn = 
    opcode1 "grain2" [ getPValue kcps,  getPValue kfmd
                     , getPValue kgdur, getPValue iovrlp
                     , getPValue kfn,   getPValue iwfn ] 



grain3 :: KSig -> KSig -> KSig -> KSig -> KSig -> KSig
       -> IInt -> TableIx -> TableIx -> KSig -> KSig
       -> GenASig
grain3 kcps kphs kfmd kpmd kgdur kdens imaxovr kfn iwfn kfrpow kprpow = 
    opcode1 "grain3" [ getPValue kcps,    getPValue kphs
                     , getPValue kfmd,    getPValue kpmd
                     , getPValue kgdur,   getPValue kdens
                     , getPValue imaxovr, getPValue kfn
                     , getPValue iwfn,    getPValue kfrpow
                     , getPValue kprpow ] 

-- |
-- 
-- > granule : xamp * ivoice * iratio * imode * ithd
-- >           ifn * ipshift * igskip * igskip_os * 
-- >           ilength * kgap * igap_os * kgsize * 
-- >           igsize_os * iatt * idec
-- >          -> ares
--
granule         :: IKA_Signal a 
                => Sig a -> IInt -> IFloat
                -> IInt -> IFloat -> TableIx
                -> IInt -> IFloat -> IFloat
                -> IFloat -> KSig -> IFloat 
                -> KSig -> IFloat -> IFloat 
                -> IFloat                
                -> GenASig 
granule xamp ivoice iratio imode ithd ifn ipshift igskip igskip_os
        ilength kgap igap_os kgsize igsize_os iatt idec = 
    opcode1 "granule" [ getPValue xamp,      getPValue ivoice
                      , getPValue iratio,    getPValue imode
                      , getPValue ithd,      getPValue ifn
                      , getPValue ipshift,   getPValue igskip
                      , getPValue igskip_os, getPValue ilength
                      , getPValue kgap,      getPValue igap_os
                      , getPValue kgsize,    getPValue igsize_os
                      , getPValue iatt,      getPValue idec ]



-- Note - not all k rate values are /signals/ (reals) the can be 
-- function table numbers as well. For these we use TableIx 
-- rather than KSig.

partikkel :: ASig -> KSig -> TableIx -> ASig -> KSig
          -> TableIx -> TableIx -> TableIx -> KSig -> KSig 
          -> KSig -> KSig -> TableIx -> KSig -> KSig
          -> TableIx -> TableIx -> ASig -> TableIx -> KSig 
          -> TableIx -> KSig -> KSig -> KSig -> TableIx
          -> KSig -> TableIx -> TableIx -> TableIx -> TableIx
          -> TableIx -> ASig -> ASig -> ASig -> ASig
          -> KSig -> KSig -> KSig -> KSig -> IInt 
          -> GenASig
partikkel agrainfreq kdistribution idisttab async kenv2amt
          ienv2tab ienv_attack ienv_decay ksustain_amount ka_d_ratio
          kduration kamp igainmasks kwavfreq ksweepshape
          iwavfreqstarttab iwavfreqendtab awavfm ifmamptab kfmenv
          icosine ktraincps knumpartials kchroma ichannelmasks 
          krandommask kwaveform1 kwaveform2 kwaveform3 kwaveform4
          iwaveamptab asamplepos1 asamplepos2 asamplepos3 asamplepos4
          kwavekey1 kwavekey2 kwavekey3 kwavekey4 imax_grains = 
    opcode1 "partikkel" [ getPValue agrainfreq,      getPValue kdistribution 
                        , getPValue idisttab,        getPValue async
                        , getPValue kenv2amt,        getPValue ienv2tab 
                        , getPValue ienv_attack,     getPValue ienv_decay
                        , getPValue ksustain_amount, getPValue ka_d_ratio
                        , getPValue kduration,       getPValue kamp
                        , getPValue igainmasks,      getPValue kwavfreq
                        , getPValue ksweepshape,     getPValue iwavfreqstarttab
                        , getPValue iwavfreqendtab,  getPValue awavfm
                        , getPValue ifmamptab,       getPValue kfmenv
                        , getPValue icosine,         getPValue ktraincps
                        , getPValue knumpartials,    getPValue kchroma
                        , getPValue ichannelmasks,   getPValue krandommask
                        , getPValue kwaveform1,      getPValue kwaveform2
                        , getPValue kwaveform3,      getPValue kwaveform4
                        , getPValue iwaveamptab,     getPValue asamplepos1
                        , getPValue asamplepos2,     getPValue asamplepos3
                        , getPValue asamplepos4,     getPValue kwavekey1
                        , getPValue kwavekey2,       getPValue kwavekey3
                        , getPValue kwavekey4,       getPValue imax_grains ]




--------------------------------------------------------------------------------
-- Models and emulations

moog :: KSig -> KSig -> KSig 
     -> KSig -> KSig -> KSig
     -> TableIx -> TableIx -> TableIx
     -> GenASig
moog kamp kfreq kfiltq kfiltrate kvibf kvamp iafn iwfn ivfn = 
    opcode1 "moog" [ getPValue kamp,   getPValue kfreq
                   , getPValue kfiltq, getPValue kfiltrate
                   , getPValue kvibf,  getPValue kvamp
                   , getPValue iafn,   getPValue iwfn
                   , getPValue ivfn ]


-- | idecay - default is 0
--
shaker :: KSig -> KSig -> KSig 
       -> KSig -> KSig -> IFloat
       -> GenASig
shaker kamp kfreq kbeans kdamp ktimes idecay = 
    opcode1 "shaker" [ getPValue kamp,   getPValue kfreq
                     , getPValue kbeans, getPValue kdamp
                     , getPValue ktimes, getPValue idecay ]


marimba :: KSig -> KSig -> IFloat -> IFloat 
        -> IInt  -> KSig -> KSig 
        -> TableIx  -> IFloat
        -> GenASig
marimba kamp kfreq ihrd ipos imp kvibf kvamp ivibfn idec = 
    opcode1 "marimba" [ getPValue kamp,  getPValue kfreq
                      , getPValue ihrd,  getPValue ipos
                      , getPValue imp,   getPValue kvibf
                      , getPValue kvamp, getPValue ivibfn
                      , getPValue idec ]

vibes :: KSig -> KSig -> IFloat -> IFloat 
      -> IInt  -> KSig -> KSig   
      -> TableIx  -> IFloat
      -> GenASig
vibes kamp kfreq ihrd ipos imp kvibf kvamp ivibfn idec = 
    opcode1 "vibes" [ getPValue kamp,  getPValue kfreq
                      , getPValue ihrd,  getPValue ipos
                      , getPValue imp,   getPValue kvibf
                      , getPValue kvamp, getPValue ivibfn
                      , getPValue idec ]

-- | iminfreq - default 0
--
mandol :: KSig -> KSig -> KSig 
       -> KSig -> KSig -> KSig 
       -> IInt -> IFloat
       -> GenASig
mandol kamp kfreq kpluck kdetune kgain ksize ifn iminfreq = 
    opcode1 "marimba" [ getPValue kamp,   getPValue kfreq
                      , getPValue kpluck, getPValue kdetune
                      , getPValue kgain,  getPValue ksize
                      , getPValue ifn,    getPValue iminfreq ]


gogobel :: KSig  -> KSig 
        -> IFloat -> IFloat -> IFloat 
        -> KSig  -> KSig  -> TableIx
        -> GenASig
gogobel kamp kfreq ihrd ipos imp kvibf kvamp ivfn = 
    opcode1 "gogobel" [ getPValue kamp,  getPValue kfreq
                      , getPValue ihrd,  getPValue ipos
                      , getPValue imp,   getPValue kvibf
                      , getPValue kvamp, getPValue ivfn ]


voice :: KSig -> KSig -> KSig 
      -> KSig -> KSig -> KSig
      -> TableIx -> TableIx
      -> GenASig
voice kamp kfreq kphoneme kform kvibf kvamp ifn ivfn = 
    opcode1 "voice" [ getPValue kamp,     getPValue kfreq
                    , getPValue kphoneme, getPValue kform
                    , getPValue kvibf,    getPValue kvamp
                    , getPValue ifn,      getPValue ivfn ]

lorenz :: KSig  -> KSig  -> KSig   -> KSig 
       -> IFloat -> IFloat -> IFloat -> IFloat
       -> GenSig3 ARate
lorenz ks kr kb kh ix iy iz iskip =  
    opcode1 "lorenz" [ getPValue ks, getPValue kr
                     , getPValue kb, getPValue kh
                     , getPValue ix, getPValue iy
                     , getPValue iz, getPValue iskip ]

planet :: KSig  -> KSig   -> KSig 
       -> IFloat -> IFloat -> IFloat 
       -> IFloat -> IFloat -> IFloat 
       -> IFloat -> IFloat
       -> GenSig3 ARate
planet kmass1 kmass2 ksep ix iy iz ivx ivy ivz idelta ifriction = 
    opcode1 "planet" [ getPValue kmass1, getPValue kmass2
                     , getPValue ksep,   getPValue ix
                     , getPValue iy,     getPValue iz
                     , getPValue ivx,    getPValue ivy
                     , getPValue ivz,    getPValue idelta
                     , getPValue ifriction ]



--------------------------------------------------------------------------------
-- Random noise generators



rand :: KA_Signal a => Sig a -> GenSig a
rand xamp = 
    opcode1 "rand" [ getPValue xamp ]


randh :: KA_Signal a => Sig a -> Sig a -> GenSig a
randh xamp xcps = 
    opcode1 "rand" [ getPValue xamp, getPValue xcps ]


randi :: KA_Signal a => Sig a -> Sig a -> GenSig a
randi xamp xcps = 
    opcode1 "rand" [ getPValue xamp, getPValue xcps ]



linrand :: IKA_Signal a =>  KSig -> GenSig a
linrand krange = 
    opcode1 "linrand" [ getPValue krange ]



trirand ::  IKA_Signal a => KSig -> GenSig a
trirand krange = 
    opcode1 "trirand" [ getPValue krange ]



exprand :: IKA_Signal a => KSig -> GenSig a
exprand krange = 
    opcode1 "exprand" [ getPValue krange ]


bexprand :: IKA_Signal a => KSig -> GenSig a
bexprand krange = 
    opcode1 "bexprand" [ getPValue krange ]


cauchy :: IKA_Signal a => KSig -> GenSig a
cauchy kalpha = 
    opcode1 "cauchy" [ getPValue kalpha ]


pcauchy :: IKA_Signal a => KSig -> GenSig a
pcauchy kalpha = 
    opcode1 "pcauchy" [ getPValue kalpha ]


poisson :: IKA_Signal a =>  KSig -> GenSig a
poisson klambda = 
    opcode1 "poisson" [ getPValue klambda ]


gauss :: IKA_Signal a => KSig -> GenSig a
gauss krange = 
    opcode1 "gauss" [ getPValue krange ]

weibull :: IKA_Signal a => KSig -> KSig -> GenSig a
weibull ksigma ktau = 
   opcode1 "weibull" [ getPValue ksigma, getPValue ktau ]


betarand :: IKA_Signal a => KSig -> KSig -> KSig -> GenSig a
betarand krange kalpha kbeta = 
    opcode1 "betarand" [ getPValue krange, getPValue kalpha
                       , getPValue kbeta ]


-- Note - can make IRate value from a KRate value, odd...

unirand :: IKA_Signal a => KSig -> GenSig a
unirand krange = 
    opcode1 "unirand" [ getPValue krange ]



--------------------------------------------------------------------------------
-- Waveguide physical modeling

pluck  :: KSig -> KSig -> IFloat -> TableIx -> IInt -> GenASig
pluck kamp kcps icps ifn imeth = 
    opcode1 "pluck" [ getPValue kamp, getPValue kcps
                    , getPValue icps, getPValue ifn
                    , getPValue imeth ]


repluck :: IFloat -> KSig -> IFloat -> KSig -> KSig -> ASig -> GenASig
repluck iplk kamp icps kpick krefl axcite =
    opcode1 "repluck" [ getPValue iplk,  getPValue kamp
                      , getPValue icps,  getPValue kpick
                      , getPValue krefl, getPValue axcite ]


wgbow :: KSig -> KSig -> KSig -> KSig -> KSig -> KSig -> TableIx -> GenASig
wgbow kamp kfreq kpres krat kvibf kvamp ifn =
    opcode1 "repluck" [ getPValue kamp,  getPValue kfreq
                      , getPValue kpres, getPValue krat
                      , getPValue kvibf, getPValue kvamp
                      , getPValue ifn ]



wgbowedbar :: KSig -> KSig -> KSig -> KSig -> KSig -> GenASig
wgbowedbar kamp kfreq kpos kbowpres kgain = 
    opcode1 "wgbowedbar" [ getPValue kamp, getPValue kfreq
                         , getPValue kpos, getPValue kbowpres
                         , getPValue kgain ]
             


wgbrass :: KSig -> KSig -> KSig -> IFloat -> KSig -> KSig -> TableIx 
        -> GenASig
wgbrass kamp kfreq ktens iatt kvibf kvamp ifn = 
    opcode1 "wgbrass" [ getPValue kamp,  getPValue kfreq
                      , getPValue ktens, getPValue iatt
                      , getPValue kvibf, getPValue kvamp
                      , getPValue ifn ]

wgclar :: KSig -> KSig -> KSig -> IFloat -> IFloat
       -> KSig -> KSig -> KSig -> TableIx
       -> GenASig
wgclar kamp kfreq kstiff iatt idetk kngain kvibf kvamp ifn = 
    opcode1 "wgclar" [ getPValue kamp,   getPValue kfreq
                     , getPValue kstiff, getPValue iatt
                     , getPValue idetk,  getPValue kngain
                     , getPValue kvibf,  getPValue kvamp
                     , getPValue ifn ]

wgflute :: KSig -> KSig -> KSig -> IFloat -> IFloat
        -> KSig -> KSig -> KSig -> TableIx
       -> GenASig
wgflute kamp kfreq kjet iatt idetk kngain kvibf kvamp ifn = 
    opcode1 "wgflute" [ getPValue kamp,   getPValue kfreq
                      , getPValue kjet,   getPValue iatt
                      , getPValue idetk,  getPValue kngain
                      , getPValue kvibf,  getPValue kvamp
                      , getPValue ifn ]

wgpluck :: IFloat -> IFloat -> KSig -> IFloat -> IFloat -> IFloat -> ASig
        -> GenASig
wgpluck icps iamp kpick iplk idamp ifilt axcite = 
    opcode1 "wgpluck" [ getPValue icps,  getPValue iamp
                      , getPValue kpick, getPValue iplk
                      , getPValue idamp, getPValue ifilt
                      , getPValue axcite ]

wgpluck2 :: IFloat -> KSig -> IFloat -> KSig -> KSig -> GenASig
wgpluck2 iplk kamp icps kpick krefl = 
    opcode1 "wgpluck2" [ getPValue iplk, getPValue kamp
                       , getPValue icps, getPValue kpick
                       , getPValue krefl ]

wguide1 :: KA_Signal a => ASig -> Sig a -> KSig -> KSig -> GenASig
wguide1 asig xfreq kcutoff kfeedback = 
    opcode1 "wguide1" [ getPValue asig,    getPValue xfreq
                      , getPValue kcutoff, getPValue kfeedback ]


wguide2 :: (KA_Signal a, KA_Signal b)
        => ASig -> Sig a -> Sig b -> KSig -> KSig -> KSig -> KSig -> GenASig
wguide2 asig xfreq1 xfreq2 kcutoff1 kcutoff2 kfeedback1 kfeedback2 =
    opcode1 "wguide2" [ getPValue asig,      getPValue xfreq1
                      , getPValue xfreq2,    getPValue kcutoff1
                      , getPValue kcutoff2,  getPValue kfeedback1
                      , getPValue kfeedback2 ]

